import io
import structsocket

class Connection:
	def __init__(self, homeswitch, conn, addr):
		self.homeswitch = homeswitch
		self.conn = conn
		self.addr = addr
		
		self.struct = structsocket.StructSocket(self.conn)
		self.struct.add_struct("char", "c")
		self.struct.add_struct("byte", "b")
		self.struct.add_struct("int", "!i")
		
		self.homeswitch.on_connection_create(self)
		
		io.get_default_io().register(self, io.POLLIN)
	
	def fileno(self):
		return self.conn.fileno()
	
	def on_io(self, state):
		try:
			data = self.struct.get_byte()
			if data == "":
				raise EOFError
			
			handler = \
			{
				1: self.on_switch_on,
				2: self.on_switch_off,
				3: self.on_list_rooms,
				4: self.on_list_switches,
				5: self.on_edit_room,
				6: self.on_edit_switch,
				7: self.on_delete_room,
				8: self.on_delete_switch
			}
			
			if data in handler:
				self.struct.write_byte(data)
				handler[data]()
			else:
				self.struct.write_byte(0)
		except EOFError:
			io.get_default_io().unregister(self)
			self.homeswitch.on_connection_destroy(self)
	
	def send_string(self, string):
		if not isinstance(string, str):
			string = string.encode("utf-8")
		
		self.struct.write_int(len(string))
		for c in string:
			self.struct.write_char(c)
	
	def get_string(self):
		string = ""
		length = self.struct.get_int()
		
		while len(string) < length:
			string += self.struct.get_char()
		
		return string.encode("utf-8")
	
	def on_switch_on(self):
		id = self.struct.get_int()
		self.homeswitch.switches[id].switch_on()
	
	def on_switch_off(self):
		id = self.struct.get_int()
		self.homeswitch.switches[id].switch_off()
	
	def on_list_rooms(self):
		self.struct.write_int(len(self.homeswitch.rooms))
		
		for i,label in self.homeswitch.rooms.items():
			self.struct.write_int(i)
			self.send_string(label)
	
	def on_list_switches(self):
		self.struct.write_int(len(self.homeswitch.switches))
		
		for i,data in self.homeswitch.switches.items():
			self.struct.write_int(i)
			self.struct.write_byte(data.active)
			self.struct.write_int(data.system_code)
			self.struct.write_int(data.unit_code)
			self.struct.write_int(data.room)
			self.send_string(data.label)
	
	def on_edit_room(self):
		id    = self.struct.get_int()
		label = self.get_string()
		
		if id == -1:
			id = 0
			while id in self.homeswitch.rooms:
				id += 1
		
		self.homeswitch.rooms[id] = label
		
		self.homeswitch.save()
	
	def on_edit_switch(self):
		id          = self.struct.get_int()
		system_code = self.struct.get_int()
		unit_code   = self.struct.get_int()
		room        = self.struct.get_int()
		label       = self.get_string()
		
		if id == -1:
			id = 0
			while id in self.homeswitch.switches:
				id += 1
		
		if id in self.homeswitch.switches:
			self.homeswitch.switches[id].system_code = system_code
			self.homeswitch.switches[id].unit_code   = unit_code
			self.homeswitch.switches[id].room        = room
			self.homeswitch.switches[id].label       = label
		else:
			self.homeswitch.switches[id] = switch.Switch(self, room, label, system_code, unit_code)
		
		self.homeswitch.save()
	
	def on_delete_room(self):
		id = self.struct.get_int()
		
		if not id in self.homeswitch.rooms:
			self.struct.write_byte(0)
			return
		
		for id in self.homeswitch.switches:
			if self.homeswitch.switches[id].room == id:
				self.struct.write_byte(0)
				return
		
		del self.homeswitch.rooms[id]
		self.struct.write_byte(1)
	
	def on_delete_switch(self):
		id = self.struct.get_int()
		
		if not id in self.homeswitch.switches:
			self.struct.write_byte(0)
			return
		
		del self.homeswitch.switches[id]
		self.struct.write_byte(1)
	

